package com.reggie.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.reggie.acl.dataobject.AddressBook;
import com.reggie.acl.dataobject.OrderDetail;
import com.reggie.acl.dataobject.Orders;
import com.reggie.acl.dataobject.ShoppingCart;
import com.reggie.acl.dataobject.User;
import com.reggie.acl.mapper.OrdersMapper;
import com.reggie.common.enums.ResponseCode;
import com.reggie.common.exception.ReggieException;
import com.reggie.service.model.bo.OrdersBO;
import com.reggie.service.model.request.OrdersPageRequest;
import com.reggie.service.service.AddressBookService;
import com.reggie.service.service.OrderDetailService;
import com.reggie.service.service.OrdersService;
import com.reggie.service.service.ShoppingCartService;
import com.reggie.service.service.UserService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author yth
 * @since 2023-02-04
 */
@Service
public class OrdersServiceImpl implements OrdersService {

    @Autowired
    private OrdersMapper ordersMapper;

    @Autowired
    private AddressBookService addressBookService;

    @Autowired
    private UserService userService;

    @Autowired
    private ShoppingCartService shoppingCartService;

    @Autowired
    private OrderDetailService orderDetailService;

    private void addDetail(final List<OrdersBO> ordersBOS) {
        List<Long> collect = ordersBOS.stream()
                .map(OrdersBO::getId)
                .collect(Collectors.toList());
        List<OrderDetail> orderDetails = orderDetailService.getByOrderIds(collect);
        Map<Long, List<OrderDetail>> map = orderDetails.stream()
                .collect(Collectors.groupingBy(OrderDetail::getOrderId));
        ordersBOS.forEach(
                e -> e.setOrderDetails(map.getOrDefault(e.getId(), new ArrayList<>(8))));
    }

    @Override
    @Transactional
    public void submit(Orders orders) {
        long userId = orders.getUserId();
        // 查询地址数据
        AddressBook addressBook = addressBookService.getDefault(userId)
                .orElseThrow(() -> new ReggieException(ResponseCode.CLIENT_ERROR, "下单失败，地址信息有误"));

        // 查询用户数据
        User user = userService.getById(userId)
                .orElseThrow(() -> new ReggieException(ResponseCode.CLIENT_ERROR, "身份验证失败，请重试"));
        // 查询用户购物车
        List<ShoppingCart> shoppingCarts = shoppingCartService.listByUserId(userId);
        if (CollectionUtils.isEmpty(shoppingCarts)) {
            throw new ReggieException(ResponseCode.CLIENT_ERROR, "下单失败，购物车是空的");
        }
        // 计算总金额
        BigDecimal totalMoney = shoppingCarts.stream()
                .map(e -> e.getAmount().multiply(new BigDecimal(e.getNumber())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // 封装数据并保存
        long number = IdWorker.getId();
        orders.setNumber(String.valueOf(number));
        orders.setStatus(2);    // 待派送
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setAmount(totalMoney);
        orders.setPhone(user.getPhone());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        orders.setUserName(user.getName());
        orders.setConsignee(addressBook.getConsignee());
        ordersMapper.insert(orders);
        // 添加订单详情
        long ordersId = orders.getId();
        List<OrderDetail> orderDetails = shoppingCarts.stream()
                .map(e -> {
                    OrderDetail detail = new OrderDetail();
                    BeanUtils.copyProperties(e, detail, "id");
                    return detail;
                })
                .collect(Collectors.toList());
        orderDetails.forEach(e -> e.setOrderId(ordersId));
        orderDetailService.save(orderDetails);
        // 清空购物车
        shoppingCartService.removeByUserId(userId);
    }


    @Override
    @Transactional
    public IPage<OrdersBO> page(OrdersPageRequest ordersPageRequest, boolean withDetail) {
        long page = ordersPageRequest.getPage();
        long pageSize = ordersPageRequest.getPageSize();
        Long userId = ordersPageRequest.getUserId();
        String number = ordersPageRequest.getNumber();
        LocalDateTime beginTime = ordersPageRequest.getBeginTime();
        LocalDateTime endTime = ordersPageRequest.getEndTime();

        LambdaQueryWrapper<Orders> wrapper = Wrappers.lambdaQuery(Orders.class)
                .eq(userId != null, Orders::getUserId, userId)
                .eq(number != null, Orders::getNumber, number)
                .between(beginTime != null && endTime != null, Orders::getCreateTime, beginTime, endTime)
                .orderByDesc(Orders::getCreateTime);
        Page<Orders> pageInfo = ordersMapper.selectPage(new Page<>(page, pageSize), wrapper);
        IPage<OrdersBO> dtoPage = pageInfo.convert(OrdersBO::new);
        if (withDetail) {
            addDetail(dtoPage.getRecords());
        }
        return dtoPage;
    }


    @Override
    public boolean updateById(Orders orders) {
        return ordersMapper.updateById(orders) > 0;
    }

    @Override
    @Transactional
    public void again(long orderId, long userId) {
        Orders orders = ordersMapper.selectById(orderId);
        long ordersUserId = orders.getUserId();
        if (!Objects.equals(ordersUserId, userId)) {
            throw new ReggieException(ResponseCode.CLIENT_ERROR, "非法操作，您不可以再来一次其它用户的订单");
        }
        // 得到默认地址
        AddressBook addressBook = addressBookService.getDefault(ordersUserId)
                .orElseThrow(() -> new ReggieException(ResponseCode.CLIENT_ERROR, "下单失败，地址信息有误"));

        // 查询用户数据
        User user = userService.getById(ordersUserId)
                .orElseThrow(() -> new ReggieException(ResponseCode.CLIENT_ERROR, "身份验证失败，请重试"));
        // 查询订单详情
        List<OrderDetail> details = orderDetailService.getByOrderId(orderId);
        // 封装数据
        orders.setId(null);
        long number = IdWorker.getId();
        orders.setNumber(String.valueOf(number));
        orders.setStatus(2);    // 待派送
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setPhone(user.getPhone());
        orders.setUserName(user.getName());
        orders.setAddress((addressBook.getProvinceName() == null ? "" : addressBook.getProvinceName())
                + (addressBook.getCityName() == null ? "" : addressBook.getCityName())
                + (addressBook.getDistrictName() == null ? "" : addressBook.getDistrictName())
                + (addressBook.getDetail() == null ? "" : addressBook.getDetail()));
        orders.setConsignee(addressBook.getConsignee());
        ordersMapper.insert(orders);
        // 添加订单详情
        long newOrderId = orders.getId();
        for (OrderDetail detail : details) {
            detail.setId(null);
            detail.setOrderId(newOrderId);
        }
        orderDetailService.save(details);
    }
}
